﻿using System;
using System.Collections.Generic;
using System.Text;
using Castle.Windsor;
using FD.RemoteAssistant.Core.Containers;
using System.Linq;
using System.Reflection;
using Castle.MicroKernel.Registration;
using FD.RemoteAssistant.Core;
using FD.RemoteAssistant.JsonEx;

namespace FDRemoteAssistant2
{
    /*
     * CreatedOn: 2018-05-15
     * CreatedBy: Jackie Lee(天宇遊龍)
     */
    /// <summary>
    /// 使用castle默认容器
    /// </summary>
    public class DefaultContainer : IContainer
    {
        private IWindsorContainer _container;

        public List<Type> Types { get; } = new List<Type>();

        public DefaultContainer(IEnumerable<AssemblyName> assemblies, Assembly assemblyExec)
        {
            Action<Assembly> resolve = assembly =>
             {
                 var types = assembly.GetExportedTypes();
                 foreach (var type in types)
                 {
                     if (!Types.Contains(type))
                     {
                         Types.Add(type);
                     }
                 }
             };

            foreach (var asm in assemblies)
            {
                var assembly = Assembly.Load(asm);
                resolve(assembly);
            }
            resolve(assemblyExec);
        }

        public void Register()
        {
            _container = new WindsorContainer();
            _container.Register(Component.For<ISerializer, JsonSerializer>());
            var interClxs = Types.Where(t => !t.IsAbstract && t.IsClass && t.GetInterfaces().Length > 0
            && !typeof(ISerializer).IsAssignableFrom(t)
            ).ToList();
            interClxs.ForEach(t =>
            {
                var interTypes = t.GetInterfaces().Where(tt=> tt.FullName.StartsWith("FD")).ToList();
                interTypes.ForEach(type =>
                {
                    _container.Register(Component.For(type).ImplementedBy(t));
                });
            });
        }

        public T Resolve<T>()
        {
            var result = Resolve(typeof(T));
            if (result != null)
            {
                return (T)result;
            }
            return default(T);
        }

        public object Resolve(Type type)
        {
            return _container.Resolve(type);
        }

        public IEnumerable<T> ResolveAll<T>()
        {
            var result = ResolveAll(typeof(T));
            if (result != null)
            {
                var enumerator = result.GetEnumerator();
                var res = new List<T>();
                while (enumerator.MoveNext())
                {
                    res.Add((T)enumerator.Current);
                }
                return res;
            }
            return default(IEnumerable<T>);
        }

        public IEnumerable<object> ResolveAll(Type type)
        {
            var res = new List<object>();
            var ars = _container.ResolveAll(type);
            var enumer = ars.GetEnumerator();
            while (enumer.MoveNext())
            {
                res.Add(enumer.Current);
            }
            return res;
        }
    }
}
